package com.koron.util;

import java.io.*;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XMLUtil {
	/**
	 * 把NodeList转换成element队列
	 * 
	 * @param nl
	 *            Nodelist
	 * @return Element队列
	 * 
	 */
	private static ArrayList<Element> nodelistToElement(NodeList nl) {
		ArrayList<Element> ret = new ArrayList<Element>();
		for (int i = 0; i < nl.getLength(); i++) {
			if (nl.item(i) instanceof Element)
				ret.add((Element) nl.item(i));
		}
		return ret;
	}

	/**
	 * 根据tag标签，找到元素的子元素
	 * 
	 * @param el
	 *            xml元素
	 * @param tag
	 *            标签，支持xpath
	 * @return 子元素队列
	 */
	public static ArrayList<Element> getChildrenByTag(Element el, String tag) {
		return getElementByXPath(el, tag);
	}

	/**
	 * 把源XML元素，根据xslt样式转换生成目标样式
	 * 
	 * @param element
	 *            元素
	 * @param source
	 *            样式
	 * @return 经过转换过后的元素
	 */
	public static StringBuffer transfer(Element element, StreamSource source) {
		try {
			StringWriter sw = new StringWriter();
			Transformer trans = null;
			if (source != null)
				trans = TransformerFactory.newInstance().newTransformer(source);
			else
				trans = TransformerFactory.newInstance().newTransformer();
			trans.transform(new DOMSource(element), new StreamResult(sw));
			sw.close();
			return sw.getBuffer();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 根据xpath从xml元素中找到相应的元素
	 * 
	 * @param el
	 *            xml Element
	 * @param name
	 *            xpath路径
	 * @return 对应的元素队列
	 */
	public static ArrayList<Element> getElementByXPath(Element el, String name) {
		try {
			NodeList nl = (NodeList) XPathFactory.newInstance().newXPath().evaluate(name, el, XPathConstants.NODESET);
			return nodelistToElement(nl);
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 字符串转换成 {@link Document}
	 * 
	 * @param source
	 * @return
	 */
	public static Document stringToDocument(final String source) {
		String tmp = source.trim();
		if (!tmp.startsWith("<?xml")) {
			tmp = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + tmp;
		}
		String encode = "utf-8";
		Pattern p = Pattern.compile("<?.*encoding=\"([^ ]*)\".*?>");
		Matcher m = p.matcher(tmp);
		if (m.find()) {
			encode = m.group(1);
		}
		try {
			return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(tmp.getBytes(encode)));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 把一个XML元素转换成字符串
	 * 
	 * @param element
	 *            XML元素
	 * @return 字符串，带有<?xml?>标签
	 */
	public static StringBuffer elementToString(final Element element) {
		return transfer(element, null);
	}

	public static void main(String[] args) {
		try {
			FileInputStream fins = new FileInputStream("c:\\xml.txt");
			Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fins);
			NodeList nl = (NodeList) XPathFactory.newInstance().newXPath()
			.evaluate("data_row/requestcode", doc.getDocumentElement(), XPathConstants.NODESET);
			for(int i = 0;i<nl.getLength();i++)
			{
				if(nl.item(i) instanceof Element)
				{
					System.out.println("i:"+((Element)nl.item(i)).getTextContent());
				}
			}
			fins.close();
		
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
		
	}
}
